<div class="content-section introduction">
    <div class="feature-intro">
        <h1>DataTable <span>Row Group</span></h1>
        <p>It is easy to implement row grouping using the flexible template driven approach of the p-table. In this example, sorting
            is enabled by default to sort the data by brand initially and then a rowGroupMetadata object is created to
            represent how many rows a brand should span along with the rowIndex of the group. Similarly multiple field grouping can be implemented as well.
        </p>
    </div>
    <app-demoActions github="table" stackblitz="tablerowgroup-demo"></app-demoActions>
</div>

<div class="content-section implementation">
    <div class="card">
        <h5>Subheader Grouping</h5>
        <p>Group customers by their representative.</p>
        <p-table [value]="customers" sortField="representative.name" sortMode="single" [scrollable]="true" scrollHeight="400px" rowGroupMode="subheader" groupRowsBy="representative.name" responsiveLayout="scroll">
            <ng-template pTemplate="header">
                <tr>
                    <th style="min-width:200px">Name</th>
                    <th style="min-width:200px">Country</th>
                    <th style="min-width:200px">Company</th>
                    <th style="min-width:200px">Status</th>
                    <th style="min-width:200px">Date</th>
                </tr>
            </ng-template>
            <ng-template pTemplate="groupheader" let-customer>
                <tr pRowGroupHeader>
                    <td colspan="5">
                        <img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/{{customer.representative.image}}" width="32" style="vertical-align: middle" />
                        <span class="font-bold ml-2">{{customer.representative.name}}</span>
                    </td>
                </tr>
            </ng-template>
            <ng-template pTemplate="groupfooter" let-customer>
                <tr class="p-rowgroup-footer">
                    <td style="min-width: 80%">
                        <div style="text-align: right; width: 100%">Total Customers</div>
                    </td>
                    <td style="width: 20%">{{calculateCustomerTotal(customer.representative.name)}}</td>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-customer let-rowIndex="rowIndex">
                <tr>
                    <td style="min-width:200px">
                        {{customer.name}}
                    </td>
                    <td style="min-width:200px">
                        <img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30">
                        <span class="image-text">{{customer.country.name}}</span>
                    </td>
                    <td style="min-width:200px">
                        {{customer.company}}
                    </td>
                    <td style="min-width:200px">
                        <span [class]="'customer-badge status-' + customer.status">{{customer.status}}</span>
                    </td>
                    <td style="min-width:200px">
                        {{customer.date}}
                    </td>
                </tr>
            </ng-template>
        </p-table>
    </div>

    <div class="card">
        <h5>Expandable Row Groups</h5>
        <p>Group customers by their representative.</p>
        <p-table [value]="customers" sortField="representative.name" sortMode="single" dataKey="representative.name" rowGroupMode="subheader" groupRowsBy="representative.name" responsiveLayout="scroll">
            <ng-template pTemplate="header">
                <tr>
                    <th>Name</th>
                    <th>Country</th>
                    <th>Company</th>
                    <th>Status</th>
                    <th>Date</th>
                </tr>
            </ng-template>
            <ng-template pTemplate="groupheader" let-customer let-rowIndex="rowIndex" let-expanded="expanded">
                <tr>
                    <td colspan="5">
                        <button type="button" pButton pRipple [pRowToggler]="customer" class="p-button-text p-button-rounded p-button-plain mr-2" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
                        <img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/{{customer.representative.image}}" width="32" style="vertical-align: middle" />
                        <span class="font-bold ml-2">{{customer.representative.name}}</span>
                    </td>
                </tr>
            </ng-template>
            <ng-template pTemplate="groupfooter" let-customer>
                <tr class="p-rowgroup-footer">
                    <td colspan="4" style="text-align: right">Total Customers</td>
                    <td>{{calculateCustomerTotal(customer.representative.name)}}</td>
                </tr>
            </ng-template>
            <ng-template pTemplate="rowexpansion" let-customer>
                <tr>
                    <td>
                        {{customer.name}}
                    </td>
                    <td>
                        <img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30">
                        <span class="image-text">{{customer.country.name}}</span>
                    </td>
                    <td>
                        {{customer.company}}
                    </td>
                    <td>
                        <span [class]="'customer-badge status-' + customer.status">{{customer.status}}</span>
                    </td>
                    <td>
                        {{customer.date}}
                    </td>
                </tr>
            </ng-template>
        </p-table>
    </div>

    <div class="card">
        <h5>RowSpan Grouping</h5>
        <p-table [value]="customers" rowGroupMode="rowspan" groupRowsBy="representative.name" sortField="representative.name" sortMode="single" responsiveLayout="scroll">
            <ng-template pTemplate="header">
                <tr>
                    <th style="width:3rem">#</th>
                    <th>Representative</th>
                    <th>Name</th>
                    <th>Country</th>
                    <th>Company</th>
                    <th>Status</th>
                    <th>Date</th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-customer let-rowIndex="rowIndex" let-rowgroup="rowgroup" let-rowspan="rowspan">
                <tr>
                    <td>{{rowIndex}}</td>
                    <td *ngIf="rowgroup" [attr.rowspan]="rowspan">
                        <img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/{{customer.representative.image}}" width="32" style="vertical-align: middle" />
                        <span class="font-bold ml-2">{{customer.representative.name}}</span>
                    </td>
                    <td>
                        {{customer.name}}
                    </td>
                    <td>
                        <img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30">
                        <span class="image-text">{{customer.country.name}}</span>
                    </td>
                    <td>
                        {{customer.company}}
                    </td>
                    <td>
                        <span [class]="'customer-badge status-' + customer.status">{{customer.status}}</span>
                    </td>
                    <td>
                        {{customer.date}}
                    </td>
                </tr>
            </ng-template>
        </p-table>
    </div>
</div>

<div class="content-section documentation">
    <p-tabView>
        <p-tabPanel header="Source">
            <a href="https://github.com/primefaces/primeng/tree/master/src/app/showcase/components/table/" class="btn-viewsource" target="_blank">
                <span>View on GitHub</span>
            </a>
            <a href="https://stackblitz.com/edit/primeng-tablerowgroup-demo" class="btn-viewsource" style="margin-left: .5em;" target="_blank">
                <span>Edit in StackBlitz</span>
            </a>

<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;div class="card"&gt;
    &lt;h5&gt;Subheader Grouping&lt;/h5&gt;
    &lt;p&gt;Group customers by their representative.&lt;/p&gt;
    &lt;p-table [value]="customers" sortField="representative.name" sortMode="single" [scrollable]="true" scrollHeight="400px" rowGroupMode="subheader" groupRowsBy="representative.name" responsiveLayout="scroll"&gt;
        &lt;ng-template pTemplate="header"&gt;
            &lt;tr&gt;
                &lt;th style="min-width:200px"&gt;Name&lt;/th&gt;
                &lt;th style="min-width:200px"&gt;Country&lt;/th&gt;
                &lt;th style="min-width:200px"&gt;Company&lt;/th&gt;
                &lt;th style="min-width:200px"&gt;Status&lt;/th&gt;
                &lt;th style="min-width:200px"&gt;Date&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="groupheader" let-customer&gt;
            &lt;tr pRowGroupHeader&gt;
                &lt;td colspan="5"&gt;
                    &lt;img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/&#123;&#123;customer.representative.image&#125;&#125;" width="32" style="vertical-align: middle" /&gt;
                    &lt;span class="font-bold ml-2"&gt;&#123;&#123;customer.representative.name&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="groupfooter" let-customer&gt;
            &lt;tr class="p-rowgroup-footer"&gt;
                &lt;td style="min-width: 80%"&gt;
                    &lt;div style="text-align: right; width: 100%"&gt;Total Customers&lt;/div&gt;
                &lt;/td&gt;
                &lt;td style="width: 20%"&gt;&#123;&#123;calculateCustomerTotal(customer.representative.name)&#125;&#125;&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="body" let-customer let-rowIndex="rowIndex"&gt;
            &lt;tr&gt;
                &lt;td style="min-width:200px"&gt;
                    &#123;&#123;customer.name&#125;&#125;
                &lt;/td&gt;
                &lt;td style="min-width:200px"&gt;
                    &lt;img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30"&gt;
                    &lt;span class="image-text"&gt;&#123;&#123;customer.country.name&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td style="min-width:200px"&gt;
                    &#123;&#123;customer.company&#125;&#125;
                &lt;/td&gt;
                &lt;td style="min-width:200px"&gt;
                    &lt;span [class]="'customer-badge status-' + customer.status"&gt;&#123;&#123;customer.status&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td style="min-width:200px"&gt;
                    &#123;&#123;customer.date&#125;&#125;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
    &lt;/p-table&gt;
&lt;/div&gt;

&lt;div class="card"&gt;
    &lt;h5&gt;Expandable Row Groups&lt;/h5&gt;
    &lt;p&gt;Group customers by their representative.&lt;/p&gt;
    &lt;p-table [value]="customers" sortField="representative.name" sortMode="single" dataKey="representative.name" rowGroupMode="subheader" groupRowsBy="representative.name" responsiveLayout="scroll"&gt;
        &lt;ng-template pTemplate="header"&gt;
            &lt;tr&gt;
                &lt;th&gt;Name&lt;/th&gt;
                &lt;th&gt;Country&lt;/th&gt;
                &lt;th&gt;Company&lt;/th&gt;
                &lt;th&gt;Status&lt;/th&gt;
                &lt;th&gt;Date&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="groupheader" let-customer let-rowIndex="rowIndex" let-expanded="expanded"&gt;
            &lt;tr&gt;
                &lt;td colspan="5"&gt;
                    &lt;button type="button" pButton pRipple [pRowToggler]="customer" class="p-button-text p-button-rounded p-button-plain mr-2" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"&gt;&lt;/button&gt;
                    &lt;img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/&#123;&#123;customer.representative.image&#125;&#125;" width="32" style="vertical-align: middle" /&gt;
                    &lt;span class="font-bold ml-2"&gt;&#123;&#123;customer.representative.name&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="groupfooter" let-customer&gt;
            &lt;tr class="p-rowgroup-footer"&gt;
                &lt;td colspan="4" style="text-align: right"&gt;Total Customers&lt;/td&gt;
                &lt;td&gt;&#123;&#123;calculateCustomerTotal(customer.representative.name)&#125;&#125;&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="rowexpansion" let-customer&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &#123;&#123;customer.name&#125;&#125;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30"&gt;
                    &lt;span class="image-text"&gt;&#123;&#123;customer.country.name&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &#123;&#123;customer.company&#125;&#125;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;span [class]="'customer-badge status-' + customer.status"&gt;&#123;&#123;customer.status&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &#123;&#123;customer.date&#125;&#125;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
    &lt;/p-table&gt;
&lt;/div&gt;

&lt;div class="card"&gt;
    &lt;h5&gt;RowSpan Grouping&lt;/h5&gt;
    &lt;p-table [value]="customers" rowGroupMode="rowspan" groupRowsBy="representative.name" sortField="representative.name" sortMode="single" responsiveLayout="scroll"&gt;
        &lt;ng-template pTemplate="header"&gt;
            &lt;tr&gt;
                &lt;th style="width:3rem"&gt;#&lt;/th&gt;
                &lt;th&gt;Representative&lt;/th&gt;
                &lt;th&gt;Name&lt;/th&gt;
                &lt;th&gt;Country&lt;/th&gt;
                &lt;th&gt;Company&lt;/th&gt;
                &lt;th&gt;Status&lt;/th&gt;
                &lt;th&gt;Date&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
        &lt;ng-template pTemplate="body" let-customer let-rowIndex="rowIndex" let-rowgroup="rowgroup" let-rowspan="rowspan"&gt;
            &lt;tr&gt;
                &lt;td&gt;&#123;&#123;rowIndex&#125;&#125;&lt;/td&gt;
                &lt;td *ngIf="rowgroup" [attr.rowspan]="rowspan"&gt;
                    &lt;img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/&#123;&#123;customer.representative.image&#125;&#125;" width="32" style="vertical-align: middle" /&gt;
                    &lt;span class="font-bold ml-2"&gt;&#123;&#123;customer.representative.name&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &#123;&#123;customer.name&#125;&#125;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30"&gt;
                    &lt;span class="image-text"&gt;&#123;&#123;customer.country.name&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &#123;&#123;customer.company&#125;&#125;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;span [class]="'customer-badge status-' + customer.status"&gt;&#123;&#123;customer.status&#125;&#125;&lt;/span&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &#123;&#123;customer.date&#125;&#125;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/ng-template&gt;
    &lt;/p-table&gt;
&lt;/div&gt;
</app-code>

<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
import &#123; Component, OnInit &#125; from '@angular/core';
import &#123; Customer &#125; from '../../domain/customer';
import &#123; CustomerService &#125; from '../../service/customerservice';

@Component(&#123;
    templateUrl: './tablerowgroupdemo.html',
    styleUrls: ['./tablerowgroupdemo.scss']
&#125;)
export class TableRowGroupDemo implements OnInit &#123;

    customers: Customer[];


    constructor(private customerService: CustomerService) &#123; &#125;

    ngOnInit() &#123;
        this.customerService.getCustomersMedium().then(data =&gt; &#123;
            this.customers = data;
        &#125;);
    &#125;

    calculateCustomerTotal(name) &#123;
        let total = 0;

        if (this.customers) &#123;
            for (let customer of this.customers) &#123;
                if (customer.representative.name === name) &#123;
                    total++;
                &#125;
            &#125;
        &#125;

        return total;
    &#125;
&#125;
</app-code>


<app-code lang="css" ngNonBindable ngPreserveWhitespaces>
:host ::ng-deep .p-rowgroup-footer td &#123;
    font-weight: 700;
&#125;

:host ::ng-deep .p-rowgroup-header &#123;
    span &#123;
        font-weight: 700;
    &#125;

    .p-row-toggler &#123;
        vertical-align: middle;
        margin-right: .25rem;
    &#125;
&#125;
</app-code>
        </p-tabPanel>

        <p-tabPanel header="StackBlitz">
            <ng-template pTemplate="content">
                <iframe src="https://stackblitz.com/edit/primeng-tablerowgroup-demo?embed=1" style="width: 100%; height: 768px; border: none;"></iframe>
            </ng-template>
        </p-tabPanel>
    </p-tabView>
</div>
